import React, {Component} from 'react';
import { observable, action, computed } from 'mobx';
import {Tools, Modal, ActionSheet, Bubble } from 'weaver-mobile';
import { MapPage, Form } from 'weaver-mobile-page';
import * as api from '../../apis/sign';
import BaseStore from '../BaseStore';
import moment from 'moment';
import {forwardViewForm} from '../../../workflowForm/util/forwardPage';
import has from 'lodash/has';
import isEmpty from 'lodash/isEmpty';
const getLabel = Tools.getLabel;

const getCurrentPosition = MapPage.getCurrentPosition;

const iconProps = {
    size: 'xs',
    color: '#E5A057',
    type: 'remind'
}

const isIPhone = new RegExp('\\biPhone\\b|\\biPod\\b', 'i').test(window.navigator.userAgent);
let wrapProps;
if (isIPhone) {
  wrapProps = {
    onTouchStart: e => e.preventDefault(),
  };
}

class SignStore extends BaseStore{
    deviceInfo;
    spinning = false;
    
    @observable currentPositionData = {};
    @observable locationLoaded = false;
    @observable baseInfo = {};
    @observable timeLineInfo = {};
    @observable locationAndWifiInfo = {};
    @observable workflowList = [];
    @observable outButtonsInfo = {};

    @observable headerRef;
    @observable showSchedual = false;

    @observable complate = false;

    @observable nearly;
    @observable _currTime = moment();

    get switchStatus(){
        const {locationInfo, wifiInfo} = this.toJS(this.locationAndWifiInfo);
        let status = false;
        if(locationInfo != null)
            status = status || locationInfo.locationcheck;
        if(wifiInfo != null)
            status = status || wifiInfo.wificheck;
        return status;
    }

    get ua(){
        return Tools.ua;
    }

    get isEMobile(){
        const ua = Tools.ua;
        return (ua != null && ua.browser.toLowerCase() == 'emobile');
    }

    @computed get currTime(){
        return this.toJS(this._currTime);
    }

    set currTime(v){
        this._currTime = v;
    }

    @action getFaceIdEnable = () => {
        const {locationInfo, wifiInfo} = this.toJS(this.locationAndWifiInfo);
        return (locationInfo.locationcheck && this.baseInfo['locationfacecheck'] == '1') || (wifiInfo.wificheck && this.baseInfo['wififacecheck'] == '1');
    }

    @action cleanMonitor = () => {
        if(this.monitor != null){
            clearInterval(this.monitor);
        }
    }

    @action init = () => {
        this.Toast.loading('loading', 0);
        api.getButtonBaseInfo().then(d => {
            if(d.status === '1' || d.status == null){
                this.baseInfo = d;
                this.currTime = (d.timemillis != null ? moment(new Date(d.timemillis)) : moment());
                this.cleanMonitor();
                this.monitor = setInterval(() => {
                    this.currTime = this.currTime.add(1, 'seconds');
                }, 1000);
                if(d.showbutton != '0'){
                    api.init().then(rs => {
                        rs.map((result, index) => {
                            if(result.status === '1' || result.status == null){
                                switch(index){
                                    case 0://timeLine info
                                        this.timeLineInfo = result;
                                        break;
                                    case 1://location&wifi info
                                        this.locationAndWifiInfo = {
                                            locationInfo: result.locationInfo,
                                            wifiInfo: result.wifiInfo
                                        }
                                        break;
                                    // case 2://workflow list
                                    //     this.workflowList = result.result;
                                    //     break;
                                }
                            }
                        });
                        this.Toast.hide();
                    });
                    this.callReduce().then(data => {
                        this.outButtonsInfo = data.outButtonsInfo;
                        setTimeout(() => {
                            this.complate = true;
                        }, 200);
                    });
                }else{
                    this.Toast.hide();
                }
            }
        })
    }
    
    @action setHeaderRef = dom => this.headerRef = dom;

    @action setShowSchedual = () => {
        this.showSchedual = !this.showSchedual;
    }

    @action callReduce = () => this.reduce([this.callGetCurrentPosition, this.getDeviceInfo, this.getOutButtons]);

    @action relocate = callback => {
        this.Toast.loading('loading', 0);
        this.callReduce().then(data => {
            this.outButtonsInfo = data.outButtonsInfo;
            api.getLocationWifiInfo().then(data => {
                if(data.status === '1' || data.status == null){
                    this.locationAndWifiInfo = {
                        locationInfo: data.locationInfo,
                        wifiInfo: data.wifiInfo
                    }
                    callback && callback();
                }
                this.Toast.hide();
            }, error => this.Toast.hide())
        }, error => this.Toast.hide());
    }

    @action refreshTimeLineData = () => {
        api.getButtons().then(data => {
            if(data.status === '1' || data.status == null){
                this.timeLineInfo = data;
            }
            this.Toast.hide();
        }, error => {this.Toast.hide();})
    }

    @action getDeviceInfo = (data = {}) => new Promise((resolve, reject) => {
        let browserType = '';
        if(this.ua != null)
            browserType = this.ua.browser.toLowerCase();
        let func = 'getClientInfo';
        if(browserType == 'dingtalk')
            func = 'getNetWorkInfo';
        
        if(window.em && window.em.checkJsApi(func)){
            window.em.ready(() => {
                window.em[func]({
                    success: (res) => {
                        // if(func == 'getNetWorkInfo'){
                        //     this.deviceInfo = {
                        //         SSID: res.ssid || res.SSID, //sid
                        //         BSSID: res.macIp || res.BSSID,//mac
                        //         networkType: res.networkType,
                        //         deviceId: res.deviceId
                        //     }
                        // }else{
                            this.deviceInfo = res;
                        // }
                        resolve({...data, deviceInfo: this.deviceInfo});
                    },
                    fail: (res) => {
                        if(browserType == 'emobile')
                            Bubble.error(getLabel('504566','无法获取设备信息'));
                        resolve({...data, deviceInfo: null});
                    }
                });
            });
        }else{
            let msg = '';
            if(window.em == null){
                msg = 'em not found, ';
            }else if(!window.em.checkJsApi(func)){
                msg = `${func} not found, `;
            }
            if(browserType == 'emobile')
                Bubble.error(`${msg}${getLabel('504566','无法获取设备信息')}`);
            resolve({...data, deviceInfo: null});
        }
    });

    @action callGetCurrentPosition = (data = {}) => new Promise((resolve, reject) => {
        this.locationLoaded = false;

        //call jsAPI
        if(window.em && window.em.checkJsApi('getLocation')){
            if(window.em && window.em.checkJsApi('dingAuthFunc')){
                window.em.dingAuthFunc();
            }
            window.em.ready(() => {
                window.em.getLocation({
                    type: 'gcj02',
                    success: (res) => {
                        this.locationLoaded = true;
                        this.currentPositionData = res;
                        isEmpty(this.currentPositionData.address) ? 
                        this.regeo(res => {
                            resolve({...data, position: this.toJS(this.currentPositionData)});
                        })
                        :
                        resolve({...data, position: this.toJS(this.currentPositionData)});
                    },
                    onLocationChanged:(res) => {
                        this.locationLoaded = true;
                        if(typeof(res) === 'string')
                            res = JSON.parse(res);
                        this.currentPositionData = res;
                        if(isEmpty(this.currentPositionData.address)){
                            this.regeo(res => {
                            })
                        } 
                    },
                    fail: (res) => {
                        Bubble.error(<div onClick={() => Bubble.error(res.errMsg)}>{getLabel('504565','无法获取定位信息')}</div>);
                        resolve({...data, position: {}});
                        //test
                        // this.currentPositionData = {address: '联航路1188号',
                        // longitude: 121.52646,
                        // latitude: 31.08013}
                        // resolve({...data, position: {address: '联航路1188号',
                        // longitude: 121.52646,
                        // latitude: 31.08013}});
                    }
                });
            });
        }else{
            let msg = '';
            if(window.em == null){
                msg = 'em not found, ';
            }else if(!window.em.checkJsApi('getLocation')){
                msg = 'getLocation not found, ';
            }
            Bubble.error(`${msg}${getLabel('504565','无法获取定位信息')}`);
            resolve({...data, position: {}});
            //test
            // setTimeout(() => {
            //     this.locationLoaded = true;
            //     this.currentPositionData = {
            //         address: '联航路1188号',
            //         longitude: 121.52646,
            //         latitude: 31.08013
            //     }
            //     resolve({...data, position: {address: '联航路1188号',
            //         longitude: 121.52646,
            //         latitude: 31.08013}});
            // }, 5000);
        }
    });

    @action getOutButtons = data => new Promise((resolve, reject) => {
        const {deviceInfo, position} = data;
        const params = {locationshowaddress: this.baseInfo.locationshowaddress};
        try{
            const {longitude, latitude} = position;
            Object.assign(params, {
                longitude,
                latitude
            });
        }catch(e){

        }
        try{
            const {SSID, BSSID, deviceId, networkType} = deviceInfo;
            Object.assign(params, {
                sid: SSID,
                mac: BSSID,
                deviceId,
                networkType
            });
        }catch(e){

        }
        const rs = {
            status: false,
            // positionObj: null,
            // wifiObj: null,
            isOutside: null,
            outsidesign: null,
            rangekey: null
        }

        api.getOutButtons(params).then(result => {
            let checkRs = '', faildKey = '';
            if(result.status === '1'){
                let checkRs = '', faildKey = '';
                const {isrange, rangekey, rangename, failkey, outsidesign, locationid} = result;

                if(isrange == '1'){
                    Object.assign(iconProps, {color: '#25E413', type: 'check-circle'});
                    checkRs = `${getLabel('500507','已进入考勤范围')} ${rangename}`;
                }else{
                    checkRs = getLabel('500508','当前不在考勤范围内');
                    faildKey = failkey;
                }
                Object.assign(rs, {checkRs, iconProps, faildKey, rangekey, status: isrange == '1', outsidesign, locationid});
            }
            resolve({...data, outButtonsInfo: rs});
        }, error => resolve({...data, outButtonsInfo: rs}));
    });

    @action showWorkflow = () => {
        api.getWorkflowList().then(data => {
            let buttons = [], workflowList = data.result;
            workflowList.map(d => {
                buttons.push({
                    content: d.title,
                    source: d,
                    onClick: () => {
                        forwardViewForm({iscreate:"1", workflowid: d.wfid});
                    }
                });
            });
            buttons.push({
                content: getLabel(32694, '取消'),
                onClick: () => {
                    this.Toast.loading('loading', 0);
                    this.refreshTimeLineData();
                }
            });
            this.showActionSheetWithOptions({
                message: getLabel('500509','请选择你需要提交的流程'),
                buttons
            })
        })
    }

    @action callSign = (data, redirectToOutsideSign, callback) => {
        if(this.spinning)
            return;
        if(this.getFaceIdEnable() && this.isEMobile && this.em && this.em.checkJsApi('securitySupport') && this.em.checkJsApi('securityEvaluation')){
            let securityType = 'faceID';
            this.em.ready(() => {
                this.em.securitySupport({
                    success: res => {
                        this.em.securityEvaluation({
                            type: securityType,
                            success: res => {
                                this.spinning = false;
                                this.punchButton(data, redirectToOutsideSign, callback);
                            },
                            fail: res => {
                                Bubble.error(<div onClick={() => Bubble.error(JSON.stringify(res))}>{getLabel('511614','人脸识别失败')}</div>);
                                this.spinning = false;
                            },
                            cancel: res => {
                                this.spinning = false;
                            }
                        })
                    },
                    fail: res => {
                        Bubble.error(<div onClick={() => Bubble.error(JSON.stringify(res))}>{getLabel('511613','人脸识别服务异常')}</div>);
                        this.spinning = false;
                    }
                })
            })
        }else
            this.punchButton(data, redirectToOutsideSign, callback);
    }

    @action callPunchButton = (params, callback) => {
        this.Toast.loading('loading', 0);
        api.punchButton(params).then(data => {
            if(data.status === '1'){
                if(data.message && data.message.trim().length >0){
                    if(data.success === '1'){
                        Bubble.success(data.message);
                    }else{
                        Bubble.warning(data.message);
                    }
                }else if(['1', '2'].indexOf(data.kqstatus) > -1){
			        Bubble.warning(getLabel(512595, '您的考勤数据异常，如有需要请提交考勤流程'));
                }
                this.refreshTimeLineData();
                callback && callback();
            }else{
                Bubble.error(data.message);
            }
            
            this.Toast.hide();
            this.spinning = false;
        }, error => {this.spinning = false})
    }

    @action punchButton = (data, redirectToOutsideSign, callback) => {
        this.spinning = true;
        // if(this.switchStatus){
        this.Toast.loading('loading', 0);
        this.callReduce().then(result => {
            const {position: {longitude, latitude, address}, deviceInfo, outButtonsInfo} = result;
            this.outButtonsInfo = outButtonsInfo;
            const ua = Tools.ua;
            const params = {...data, longitude, latitude, position: address, locationid: outButtonsInfo.locationid, locationshowaddress: this.baseInfo.locationshowaddress};
            if(deviceInfo != null){
                const {SSID, BSSID, deviceId} = deviceInfo;
                Object.assign(params, {
                    sid: SSID,
                    mac: BSSID,
                    deviceId,
                    deviceInfo: JSON.stringify(deviceInfo)
                });
            }
            has(ua, 'browser') && Object.assign(params, {browser: ua.browser});
            if(outButtonsInfo.status || !this.switchStatus){
                this.callPunchButton(params, callback);
            }else{
                this.Toast.hide();
                this.spinning = false;
                if(outButtonsInfo.outsidesign == '1'){
                    this.showAlert({
                        title: outButtonsInfo.faildKey == 'position' ? getLabel('500510','地理位置不在考勤范围内') : getLabel('507524','WIFI不在考勤范围内'),
                        message: getLabel('500511','您是否要转入外勤打卡？'),
                        okLabel: getLabel('500503','外勤打卡'),
                        cancelLabel: getLabel('500512','不需要'),
                        onOk: () => {
                            api.getLocationWifiInfo().then(data => {
                                if(data.status === '1' || data.status == null){
                                    this.locationAndWifiInfo = {
                                        locationInfo: data.locationInfo,
                                        wifiInfo: data.wifiInfo
                                    }
                                }
                                this.redirectToOutsideSignApp();
                            }, error => {
                                this.redirectToOutsideSignApp();
                            })
                        },
                        onCancel: () => {}
                    });
                }else{
                    this.showAlert({
                        title: outButtonsInfo.faildKey == 'position' ? getLabel('500510','地理位置不在考勤范围内') : getLabel('507524','WIFI不在考勤范围内'),
                        message: getLabel('504701','无法完成考勤打卡'),
                        okLabel: getLabel(33703, '确定'),
                        onOk: () => {
                        },
                        showCancel: false
                    });
                }
            }
        });
        // }
    }

    @action redirectToOutsideSignApp = () => {
        if(window.em != null && window.em.checkJsApi('openLink')){
            window.em.openLink({
              url: `/spa/hrm/static4mobile/index.html#/outSign`,
              openType: 2,
              sysId: window.localStorage.emobile_ec_id
            });
          }else{
            window.location.href = '/spa/hrm/static4mobile/index.html#/outSign';
          }
    }

    @action findNearly = () => {
        let rs;
        const position = this.toJS(this.currentPositionData);
        if(!this.locationLoaded){
            this.nearly = rs;
            return rs;
        }
        const {locationcheck, locations, locationcheckscope} = this.toJS(this.locationAndWifiInfo.locationInfo);
        if(locationcheck){
            let dis, nearlyLocation;
            locations != null && locations.map(location => {
                try{
                    const a = new window.AMap.LngLat(Number(position.longitude), Number(position.latitude));
                    const b = new window.AMap.LngLat(Number(location.longitude), Number(location.latitude));
                    let tmp = a.distance(b);
                    if(dis == null || dis > tmp){
                        dis = tmp;
                        nearlyLocation = location;
                    }
                }catch(e){
                    Bubble.error(getLabel('504567','获取考勤点失败'));
                }
            });
            rs = {
                positionObj: {
                    nearlyLocation,
                    dis,
                    locationcheckscope,
                },
                locationcheck,
                status: dis <= Number(locationcheckscope)
            };
        }
        this.nearly = rs;
        return rs;
    }

    formatUrl = params => {
        params = Object.values(params).reduce((a,b,i) => `${a}${Object.keys(params)[i]}=${b}&`, '?');
        return params.substring(0, params.length - 1);
    }

    @action regeo = callback => {
        const params = {
            key: window.gaodeMapWebKey,
            location: `${this.currentPositionData.longitude},${this.currentPositionData.latitude}`,
            radius: 1000,
            poitype: '',
            extensions: 'all',
            batch: 'false',
            roadlevel: '0'
        }
        localStorage.setItem('regeoParams', `regeoParams-${moment().format("yyyy-MM-dd HH:mm:ss")}: ${JSON.stringify(params)}`);
        if(this.currentPositionData.longitude != null){
            fetch(`https://restapi.amap.com/v3/geocode/regeo${this.formatUrl(params)}`, {method: 'GET'}).
            then(res => res.json())
            .catch(err => {
                Bubble.error(<div onClick={() => Bubble.error(JSON.stringify(err))}>call amap regeo failed</div>);
                callback && callback();
            })
            .then(data => {
                if(data.status == '1'){
                    this.currentPositionData.address = '';
                    let {formatted_address: address} = data.regeocode;
                    this.currentPositionData.address = address || '';
                }else{
                    Bubble.error(JSON.stringify(data));
                }
                
                callback && callback();
            });
        }else
            callback && callback();
    }

    @observable formStore = new Form.Store({route: '/sign/setting'});
    @action getAutoEMSet = async () => {
        const data = await api.getAutoEMSet();
        if(data.status == 1){
            this.formStore.initForm(data.formField, '/sign/setting');
        }
    }

    @action onFieldChangeHandle = async (condition, value) => {
        this.formStore.onChange(condition, value);
        const data = await api.saveAutoEMSet(this.formStore.formParams);
        if(data.status != "1"){
            Bubble.error(data.message);
        }
    }
}

export const signStore = new SignStore(); 